package com.yamanyar.weebill.domain;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.validator.NotNull;

/**
 * User object represents the user who logs into system. Every interaction with
 * system requires an user. If user is not logged, default user is the Anonymous
 * user.
 * 
 * @author Kaan Yamanyar
 * 
 */
@Entity
// email should be unique.
@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "email" }))
public class User {
	private Long id;

	private String name;

	private String lastName;

	private Date birthDay;

	private String email;

	private String password;

	private Set<Role> roles = new HashSet<Role>();

	/**
	 * Returns the e-mail of user if it is set.
	 * 
	 * @return E-mail of the user. Max 60 chars.
	 */
	@NotNull
	@Column(length = 60, name = "email")
	public String getEmail() {
		return this.email;
	}

	/**
	 * Sets user's e-mail.
	 * 
	 * @param email
	 *            E-mail which will be set for user. Max 60 chars allowed.
	 */
	public void setEmail(String email) {
		this.email = email;
	}

	/**
	 * 
	 * @return The id of user. Id is auto-generated by db.
	 */
	@Id
	@GeneratedValue
	public Long getId() {
		return this.id;
	}

	/**
	 * 
	 * Returns user's birthday.
	 * 
	 * View spesific note: Please note that this method is annonated so that it
	 * will be displayed as "MM/dd/yyyy" in view.
	 * 
	 * @return User's birthday
	 */
	// we do not need hours,minutes...
	public Date getBirthDay() {
		return this.birthDay;
	}

	/**
	 * Set the birthday of user.
	 * 
	 * @param birthDay
	 *            Format dhould
	 */
	public void setBirthDay(Date birthDay) {
		this.birthDay = birthDay;
	}

	/**
	 * Returns user's lastname. If loaded from db, it is supposed not to be
	 * null.
	 * 
	 * @return Lastname of user. Max 20 chars.
	 */
	@NotNull
	@Column(length = 20)
	public String getLastName() {
		return this.lastName;
	}

	/**
	 * Sets user's lastname
	 * 
	 * @param lastName
	 *            Lastname of user. Max 20 chars.
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	/**
	 * Returns user's name. If loaded from db, it is not supoosed to be null.
	 * 
	 * @return User's first name. Max 20 chars.
	 */

	@NotNull
	@Column(length = 20)
	public String getName() {
		return this.name;
	}

	/**
	 * Sets user's first name
	 * 
	 * @param name
	 *            first name of the user.Max 20 chars.
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Return the roles that user has. These roles are supposed to used for
	 * authentication to several services. Example of services can be creating a
	 * project, writing a comment to a task,bug etc.
	 * 
	 * @return Roles that user has.
	 * @see Role
	 */
	@ManyToMany(targetEntity = Role.class, fetch = FetchType.LAZY)
	public Set<Role> getRoles() {
		return this.roles;
	}

	/**
	 * Set the roles that user has. These roles are supposed to used for
	 * authentication to several services. Example of services can be creating a
	 * project, writing a comment to a task,bug etc.
	 * 
	 * @param roles
	 *            Set of roles that user have
	 * @see Role
	 */
	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	/**
	 * <code>toString</code> method is overriden in order to display name and
	 * lastname as representer.
	 */
	@Override
	public String toString() {
		return this.name + " " + this.lastName;
	}

	@Override
	public int hashCode() {
		if (this.id == null) {
			return 0;
		}
		return (int) (this.id / 10) + 1;
	}

	@Override
	public boolean equals(Object obj) {
		if (this.id == null) {
			return false;
		}
		if ((obj == null) || !(obj instanceof User)) {
			return false;
		}

		User that = (User) obj;

		return this.id.equals(that.getId());
	}

	/**
	 * This method is not supposed to be called by a developer.
	 * 
	 * @param id
	 */
	public void setId(Long id) {
		this.id = id;
	}

	@NotNull
	@Column(length = 12)
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}